home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 21 / AACD 21.iso / AACD / Utilities / Ghostscript / src / iutilasm.asm < prev    next >
Encoding:
Assembly Source File  |  2001-01-01  |  12.2 KB  |  698 lines

  1. ;    Copyright (C) 1989, 1992, 1993 Aladdin Enterprises.  All rights reserved.
  2. ; This file is part of AFPL Ghostscript.
  3. ; AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  4. ; distributor accepts any responsibility for the consequences of using it, or
  5. ; for whether it serves any particular purpose or works at all, unless he or
  6. ; she says so in writing.  Refer to the Aladdin Free Public License (the
  7. ; "License") for full details.
  8. ; Every copy of AFPL Ghostscript must include a copy of the License, normally
  9. ; in a plain ASCII text file named PUBLIC.  The License grants you the right
  10. ; to copy, modify and redistribute AFPL Ghostscript, but only under certain
  11. ; conditions described in the License.  Among other things, the License
  12. ; requires that the copyright notice and this notice be preserved on all
  13. ; copies.
  14.  
  15. ; $Id: iutilasm.asm,v 1.2 2000/09/19 19:00:46 lpd Exp $
  16. ; iutilasm.asm
  17. ; Assembly code for Ghostscript interpreter on MS-DOS systems
  18.  
  19.     ifdef    FOR80386
  20.  
  21.     .286c
  22.  
  23.     endif
  24.  
  25. utilasm_TEXT    SEGMENT    WORD PUBLIC 'CODE'
  26.     ASSUME    CS:utilasm_TEXT
  27.  
  28.  
  29.     ifdef    FOR80386
  30.  
  31. ; Macro for 32-bit operand prefix.
  32. OP32    macro
  33.     db    66h
  34.     endm
  35.  
  36.     endif                    ; FOR80386
  37.  
  38. ; Clear a register
  39.  
  40. clear    macro    reg
  41.     xor    reg,reg
  42.     endm
  43.  
  44.  
  45.     ifdef    FOR80386
  46.  
  47. ; Replace the multiply and divide routines in the Turbo C library
  48. ; if we are running on an 80386.
  49.  
  50. ; Macro to swap the halves of a 32-bit register.
  51. ; Unfortunately, masm won't allow a shift instruction with a count of 16,
  52. ; so we have to code it in hex.
  53. swap    macro    regno
  54.       OP32
  55.     db    0c1h,0c0h+regno,16        ; rol regno,16
  56.     endm
  57. regax    equ    0
  58. regcx    equ    1
  59. regdx    equ    2
  60. regbx    equ    3
  61.  
  62.  
  63. ; Multiply (dx,ax) by (cx,bx) to (dx,ax).
  64.     PUBLIC    LXMUL@
  65.     PUBLIC    F_LXMUL@
  66. F_LXMUL@ proc    far
  67. LXMUL@    proc    far
  68.     swap    regdx
  69.     mov    dx,ax
  70.     swap    regcx
  71.     mov    cx,bx
  72.       OP32
  73.     db    0fh,0afh,0d1h            ; imul dx,cx
  74.       OP32
  75.     mov    ax,dx
  76.     swap    regdx
  77.     ret
  78. LXMUL@    endp
  79. F_LXMUL@ endp
  80.  
  81.  
  82. ; Divide two stack operands, leave the result in (dx,ax).
  83.  
  84.     ifdef    DEBUG
  85.  
  86. setup32    macro
  87.     mov    bx,sp
  88.     push    bp
  89.     mov    bp,sp
  90.       OP32
  91.     mov    ax,ss:[bx+4]            ; dividend
  92.     endm
  93.  
  94. ret32    macro    n
  95.     mov    sp,bp
  96.     pop    bp
  97.     ret    n
  98.     endm
  99.  
  100.     else                    ; !DEBUG
  101.  
  102. setup32    macro
  103.     mov    bx,sp
  104.       OP32
  105.     mov    ax,ss:[bx+4]            ; dividend
  106.     endm
  107.  
  108. ret32    macro    n
  109.     ret    n
  110.     endm
  111.  
  112.     endif                    ; (!)DEBUG
  113.  
  114.     PUBLIC    LDIV@, LUDIV@, LMOD@, LUMOD@
  115.     PUBLIC    F_LDIV@, F_LUDIV@, F_LMOD@, F_LUMOD@
  116. F_LDIV@    proc    far
  117. LDIV@    proc    far
  118.     setup32
  119.       OP32
  120.     cwd
  121.       OP32
  122.     idiv    word ptr ss:[bx+8]        ; divisor
  123.       OP32
  124.     mov    dx,ax
  125.     swap    regdx
  126.     ret32    8
  127. LDIV@    endp
  128. F_LDIV@    endp
  129. F_LUDIV@ proc    far
  130. LUDIV@    proc    far
  131.     setup32
  132.       OP32
  133.     xor    dx,dx
  134.       OP32
  135.     div    word ptr ss:[bx+8]        ; divisor
  136.       OP32
  137.     mov    dx,ax
  138.     swap    regdx
  139.     ret32    8
  140. LUDIV@    endp
  141. F_LUDIV@ endp
  142. F_LMOD@    proc    far
  143. LMOD@    proc    far
  144.     setup32
  145.       OP32
  146.     cwd
  147.       OP32
  148.     idiv    word ptr ss:[bx+8]        ; divisor
  149.       OP32
  150.     mov    ax,dx
  151.     swap    regdx
  152.     ret32    8
  153. LMOD@    endp
  154. F_LMOD@    endp
  155. F_LUMOD@ proc    far
  156. LUMOD@    proc    far
  157.     setup32
  158.       OP32
  159.     xor    dx,dx
  160.       OP32
  161.     div    word ptr ss:[bx+8]        ; divisor
  162.       OP32
  163.     mov    ax,dx
  164.     swap    regdx
  165.     ret32    8
  166. LUMOD@    endp
  167. F_LUMOD@ endp
  168.  
  169.     else                    ; !FOR80386
  170.  
  171. ; Replace the divide routines in the Turbo C library,
  172. ; which do the division one bit at a time (!).
  173.  
  174.     PUBLIC    LDIV@, LMOD@, LUDIV@, LUMOD@
  175.     PUBLIC    F_LDIV@, F_LMOD@, F_LUDIV@, F_LUMOD@
  176.  
  177. ; Negate a long on the stack.
  178. negbp    macro    offset
  179.     neg    word ptr [bp+offset+2]        ; high part
  180.     neg    word ptr [bp+offset]        ; low part
  181.     sbb    word ptr [bp+offset+2],0
  182.     endm
  183.  
  184. ; Negate a long in (dx,ax).
  185. negr    macro
  186.     neg    dx
  187.     neg    ax
  188.     sbb    dx,0
  189.     endm
  190.  
  191. ; Divide two unsigned longs on the stack.
  192. ; Leave either the quotient or the remainder in (dx,ax).
  193. ; Operand offsets assume that bp (and only bp) has been pushed.
  194. nlo    equ    6
  195. nhi    equ    8
  196. dlo    equ    10
  197. dhi    equ    12
  198.  
  199. ; We use an offset in bx to distinguish div from mod,
  200. ; and to indicate whether the result should be negated.
  201. odiv    equ    0
  202. omod    equ    2
  203. odivneg    equ    4
  204. omodneg    equ    6
  205. F_LMOD@    proc    far
  206. LMOD@    proc    far
  207.     push    bp
  208.     mov    bp,sp
  209.     mov    bx,omod
  210.             ; Take abs of denominator
  211.     cmp    byte ptr [bp+dhi+1],bh        ; bh = 0
  212.     jge    modpd
  213.     negbp    dlo
  214. modpd:            ; Negate mod if numerator < 0
  215.     cmp    byte ptr [bp+nhi+1],bh        ; bh = 0
  216.     jge    udiv
  217.     mov    bx,omodneg
  218. negnum:    negbp    nlo
  219.     jmp    udiv
  220. LMOD@    endp
  221. F_LMOD@    endp
  222. F_LUMOD@ proc    far
  223. LUMOD@    proc    far
  224.     mov    bx,omod
  225.     jmp    udpush
  226. LUMOD@    endp
  227. F_LUMOD@ endp
  228. F_LDIV@    proc    far
  229. LDIV@    proc    far
  230.     push    bp
  231.     mov    bp,sp
  232.     mov    bx,odiv
  233.             ; Negate quo if num^den < 0
  234.     mov    ax,[bp+nhi]
  235.     xor    ax,[bp+dhi]
  236.     jge    divabs
  237.     mov    bx,odivneg
  238. divabs:            ; Take abs of denominator
  239.     cmp    byte ptr [bp+dhi+1],bh        ; bh = 0
  240.     jge    divpd
  241.     negbp    dlo
  242. divpd:            ; Take abs of numerator
  243.     cmp    byte ptr [bp+nhi+1],bh        ; bh = 0
  244.     jge    udiv
  245.     jmp    negnum
  246. LDIV@    endp
  247. F_LDIV@    endp
  248. F_LUDIV@ proc    far
  249. LUDIV@    proc    far
  250.     mov    bx,odiv
  251. udpush:    push    bp
  252.     mov    bp,sp
  253. udiv:    push    bx                ; odiv, omod, odivneg, omodneg
  254.     mov    ax,[bp+nlo]
  255.     mov    dx,[bp+nhi]
  256.     mov    bx,[bp+dlo]
  257.     mov    cx,[bp+dhi]
  258. ; Now we are dividing dx:ax by cx:bx.
  259. ; Check to see whether this is really a 32/16 division.
  260.     or    cx,cx
  261.     jnz    div2
  262. ; 32/16, check for 16- vs. 32-bit quotient
  263.     cmp    dx,bx
  264.     jae    div1
  265. ; 32/16 with 16-bit quotient, just do it.
  266.     div    bx                ; ax = quo, dx = rem
  267.     pop    bx
  268.     pop    bp
  269.     jmp    cs:xx1[bx]
  270.     even
  271. xx1    dw    offset divx1
  272.     dw    offset modx1
  273.     dw    offset divx1neg
  274.     dw    offset modx1neg
  275. modx1:    mov    ax,dx
  276. divx1:    xor    dx,dx
  277.     ret    8
  278. modx1neg: mov    ax,dx
  279. divx1neg: xor    dx,dx
  280. rneg:    negr
  281.     ret    8
  282. ; 32/16 with 32-bit quotient, do in 2 parts.
  283. div1:    mov    cx,ax                ; save lo num
  284.     mov    ax,dx
  285.     xor    dx,dx
  286.     div    bx                ; ax = hi quo
  287.     xchg    cx,ax                ; save hi quo, get lo num
  288.     div    bx                ; ax = lo quo, dx = rem
  289.     pop    bx
  290.     pop    bp
  291.     jmp    cs:xx1a[bx]
  292.     even
  293. xx1a    dw    offset divx1a
  294.     dw    offset modx1
  295.     dw    offset divx1aneg
  296.     dw    offset modx1neg
  297. divx1a:    mov    dx,cx                ; hi quo
  298.     ret    8
  299. divx1aneg: mov    dx,cx
  300.     jmp    rneg
  301. ; This is really a 32/32 bit division.
  302. ; (Note that the quotient cannot exceed 16 bits.)
  303. ; The following algorithm is taken from pp. 235-240 of Knuth, vol. 2
  304. ; (first edition).
  305. ; Start by normalizing the numerator and denominator.
  306. div2:    or    ch,ch
  307.     jz    div21                ; ch == 0, but cl != 0
  308. ; Do 8 steps all at once.
  309.     mov    bl,bh
  310.     mov    bh,cl
  311.     mov    cl,ch
  312.     xor    ch,ch
  313.     mov    al,ah
  314.     mov    ah,dl
  315.     mov    dl,dh
  316.     xor    dh,dh
  317.     rol    bx,1                ; faster than jmp
  318. div2a:    rcr    bx,1                ; finish previous shift
  319. div21:    shr    dx,1
  320.     rcr    ax,1
  321.     shr    cx,1
  322.     jnz    div2a
  323.     rcr    bx,1
  324. ; Now we can do a 32/16 divide.
  325. div2x:    div    bx                ; ax = quo, dx = rem
  326. ; Multiply by the denominator, and correct the result.
  327.     mov    cx,ax                ; save quotient
  328.     mul    word ptr [bp+dhi]
  329.     mov    bx,ax                ; save lo part of hi product
  330.     mov    ax,cx
  331.     mul    word ptr [bp+dlo]
  332.     add    dx,bx
  333. ; Now cx = trial quotient, (dx,ax) = cx * denominator.
  334.     not    dx
  335.     neg    ax
  336.     cmc
  337.     adc    dx,0                ; double-precision neg
  338.     jc    divz                ; zero quotient
  339.                         ; requires special handling
  340.     add    ax,[bp+nlo]
  341.     adc    dx,[bp+nhi]
  342.     jc    divx
  343. ; Quotient is too large, adjust it.
  344. div3:    dec    cx
  345.     add    ax,[bp+dlo]
  346.     adc    dx,[bp+dhi]
  347.     jnc    div3
  348. ; All done.  (dx,ax) = remainder, cx = lo quotient.
  349. divx:    pop    bx
  350.     pop    bp
  351.     jmp    cs:xx3[bx]
  352.     even
  353. xx3    dw    offset divx3
  354.     dw    offset modx3
  355.     dw    offset divx3neg
  356.     dw    offset modx3neg
  357. divx3:    mov    ax,cx
  358.     xor    dx,dx
  359. modx3:    ret    8
  360. divx3neg: mov    ax,cx
  361.     xor    dx,dx
  362. modx3neg: jmp    rneg
  363. ; Handle zero quotient specially.
  364. divz:    pop    bx
  365.     jmp    cs:xxz[bx]
  366.     even
  367. xxz    dw    offset divxz
  368.     dw    offset modxz
  369.     dw    offset divxz
  370.     dw    offset modxzneg
  371. divxz:    pop    bp
  372.     ret    8
  373. modxzneg: negbp    nlo
  374. modxz:    mov    ax,[bp+nlo]
  375.     mov    dx,[bp+nhi]
  376.     pop    bp
  377.     ret    8
  378. LUDIV@    endp
  379. F_LUDIV@ endp
  380.  
  381.     endif                    ; FOR80386
  382.  
  383.  
  384.     ifdef    NOFPU
  385.  
  386. ; See gsmisc.c for the C version of this code.
  387.  
  388. ; /*
  389. ;  * Floating multiply with fixed result, for avoiding floating point in
  390. ;  * common coordinate transformations.  Assumes IEEE representation,
  391. ;  * 16-bit short, 32-bit long.  Optimized for the case where the first
  392. ;  * operand has no more than 16 mantissa bits, e.g., where it is a user space
  393. ;  * coordinate (which are often integers).
  394. ;  *
  395. ;  * The assembly language version of this code is actually faster than
  396. ;  * the FPU, if the code is compiled with FPU_TYPE=0 (which requires taking
  397. ;  * a trap on every FPU operation).  If there is no FPU, the assembly
  398. ;  * language version of this code is over 10 times as fast as the
  399. ;  * emulated FPU.
  400. ;  */
  401. ; fixed
  402. ; fmul2fixed_(long /*float*/ a, long /*float*/ b)
  403. ; {
  404.  
  405.     PUBLIC    _fmul2fixed_
  406. _fmul2fixed_ proc far
  407.     push    bp
  408.     mov    bp,sp
  409. a    equ    6
  410. alo    equ    a
  411. ahi    equ    a+2
  412. b    equ    10
  413. blo    equ    b
  414. bhi    equ    b+2
  415.     push    si        ; will hold ma
  416.     push    di        ; will hold mb
  417.  
  418. ;     int e = 260 + _fixed_shift - ((
  419. ;         (((uint)(a >> 16)) & 0x7f80) + (((uint)(b >> 16)) & 0x7f80)
  420. ;       ) >> 7);
  421.  
  422.     mov    dx,[bp+ahi]
  423. ; dfmul2fixed enters here
  424. fmf:    mov    cx,260+12
  425.     mov    ax,[bp+bhi]
  426.     and    ax,7f80h
  427.     and    dx,7f80h
  428.     add    ax,dx
  429.     xchg    ah,al        ; ror ax,7 without using cl
  430.     rol    ax,1
  431.     sub    cx,ax
  432.     push    cx        ; e
  433.  
  434. ;     ulong ma = (ushort)(a >> 8) | 0x8000;
  435. ;     ulong mb = (ushort)(b >> 8) | 0x8000;
  436.  
  437.     mov    si,[bp+alo+1]    ; unaligned
  438.     clear    ax
  439.     mov    di,[bp+blo+1]    ; unaligned
  440.     or    si,8000h
  441.     or    di,8000h
  442.  
  443. ;     ulong p1 = ma * (b & 0xff);
  444.  
  445.     mov    al,[bp+blo]
  446.     mul    si
  447.  
  448. ;            (Do this later:)
  449. ;     ulong p = ma * mb;
  450.  
  451. ;     if ( (byte)a )        /* >16 mantissa bits */
  452.  
  453.     cmp    byte ptr [bp+alo],0
  454.     je    mshort
  455.  
  456. ;     {    ulong p2 = (a & 0xff) * mb;
  457. ;         p += ((((uint)(byte)a * (uint)(byte)b) >> 8) + p1 + p2) >> 8;
  458.  
  459.     mov    cx,dx
  460.     mov    bx,ax
  461.     clear    ax
  462.     mov    al,[bp+alo]
  463.     clear    dx
  464.     mov    dl,[bp+blo]
  465.     mul    dx
  466.     mov    dl,ah        ; dx is zero
  467.     add    bx,cx
  468.     adc    cx,0
  469.     clear    ax
  470.     mov    al,[bp+alo]
  471.     mul    di
  472.     add    ax,bx
  473.     adc    dx,cx
  474.  
  475. ;     }
  476.  
  477. mshort:
  478.  
  479. ;     else
  480. ;         p += p1 >> 8;
  481.  
  482.     mov    bl,ah        ; set (cx,bx) = (dx,ax) >> 8
  483.     mov    bh,dl
  484.     clear    cx
  485.     mov    cl,dh
  486.     mov    ax,si
  487.     mul    di
  488.     add    ax,bx
  489.     adc    dx,cx
  490.  
  491. ;     if ( (uint)e < 32 )        /* e = -1 is possible */
  492.  
  493.     pop    cx        ; e
  494.     cmp    cx,16
  495.     jb    shr1
  496.  
  497. ;     else if ( e >= 32 )        /* also detects a=0 or b=0 */
  498.  
  499.     cmp    cx,0
  500.     jl    eneg
  501.     sub    cx,16
  502.     cmp    cx,16
  503.     jge    shr0
  504.     mov    ax,dx
  505.     clear    dx
  506.     shr    ax,cl
  507.     jmp    ex
  508.  
  509. ;         return fixed_0;
  510.  
  511. shr0:    clear    ax
  512.     clear    dx
  513.     jmp    ex
  514.  
  515. ;     else
  516. ;         p <<= -e;
  517.  
  518.     even
  519. eneg:    neg    cx
  520.     shl    dx,cl
  521.     mov    bx,ax
  522.     shl    ax,cl
  523.     rol    bx,cl
  524.     xor    bx,ax
  525.     add    dx,bx
  526.     jmp    ex
  527.  
  528. ;         p >>= e;
  529.  
  530.     even
  531. shr1:    shr    ax,cl
  532.     mov    bx,dx
  533.     shr    dx,cl
  534.     ror    bx,cl
  535.     xor    bx,dx
  536.     add    ax,bx
  537.  
  538. ex:
  539.  
  540. ;     return ((a ^ b) < 0 ? -p : p);
  541.  
  542.     mov    cx,[bp+ahi]
  543.     xor    cx,[bp+bhi]
  544.     jge    pos
  545.     neg    dx
  546.     neg    ax
  547.     sbb    dx,0
  548. pos:
  549.  
  550. ; }
  551.  
  552. retu:    pop    di
  553.     pop    si
  554.     mov    sp,bp
  555.     pop    bp
  556.     ret
  557.  
  558. _fmul2fixed_ ENDP
  559.  
  560. ; The same routine with the first argument a double rather than a float.
  561. ; The argument is split into two pieces to reduce data movement.
  562.  
  563.     PUBLIC    _dfmul2fixed_
  564. _dfmul2fixed_ proc far
  565.     push    bp
  566.     mov    bp,sp
  567. xalo    equ    6
  568. ;b    equ    10
  569. xahi    equ    14
  570.     push    si        ; overlap this below
  571.     push    di        ; ditto
  572.  
  573. ; Shuffle the arguments and then use fmul2fixed.
  574.  
  575. ; Squeeze 3 exponent bits out of the top 35 bits of a.
  576.  
  577.     mov    dx,[bp+xahi+2]
  578.     mov    bx,0c000h
  579.     mov    ax,[bp+xahi]
  580.     and    bx,dx
  581.     mov    cx,[bp+xalo+2]
  582.     and    dx,7ffh        ; get rid of discarded bits
  583.     add    cx,cx        ; faster than shl!
  584.     jz    cz        ; detect common case
  585.     adc    ax,ax        ; faster than rcl!
  586.     adc    dx,dx
  587.     add    cx,cx
  588.     adc    ax,ax
  589.     adc    dx,dx
  590.     add    cx,cx
  591.     adc    ax,ax
  592.     mov    [bp+alo],ax
  593.     adc    dx,dx
  594.     or    dx,bx
  595.     mov    [bp+ahi],dx
  596.     jmp    fmf
  597.     even
  598. cz:    adc    ax,ax
  599.     adc    dx,dx
  600.     add    ax,ax
  601.     adc    dx,dx
  602.     add    ax,ax
  603.     mov    [bp+alo],ax
  604.     adc    dx,dx
  605.     or    dx,bx
  606.     mov    [bp+ahi],dx
  607.     jmp    fmf
  608.  
  609. _dfmul2fixed_ ENDP
  610.  
  611.     endif                    ; NOFPU
  612.  
  613.  
  614. ; Transpose an 8x8 bit matrix.  See gsmisc.c for the algorithm in C.
  615.     PUBLIC    _memflip8x8
  616. _memflip8x8 proc far
  617.     push    ds
  618.     push    si
  619.     push    di
  620.         ; After pushing, the offsets of the parameters are:
  621.         ; byte *inp=10, int line_size=14, byte *outp=16, int dist=20.
  622.     mov    si,sp
  623.     mov    di,ss:[si+14]            ; line_size
  624.     lds    si,ss:[si+10]            ; inp
  625.         ; We assign variables to registers as follows:
  626.         ; ax = AE, bx = BF, cx (or di) = CG, dx = DH.
  627.         ; Load the input data.  Initially we assign
  628.         ; ax = AB, bx = EF, cx (or di) = CD, dx = GH.
  629.     mov    ah,[si]
  630. iload    macro    reg
  631.     add    si,di
  632.     mov    reg,[si]
  633.     endm
  634.     iload    al
  635.     iload    ch
  636.     iload    cl
  637.     iload    bh
  638.     iload    bl
  639.     iload    dh
  640.     iload    dl
  641.         ; Transposition macro, see C code for explanation.
  642. trans    macro    reg1,reg2,shift,mask
  643.     mov    si,reg1
  644.     shr    si,shift
  645.     xor    si,reg2
  646.     and    si,mask
  647.     xor    reg2,si
  648.     shl    si,shift
  649.     xor    reg1,si
  650.     endm
  651.         ; Do 4x4 transpositions
  652.     mov    di,cx            ; we need cl for the shift count
  653.     mov    cl,4
  654.     trans    bx,ax,cl,0f0fh
  655.     trans    dx,di,cl,0f0fh
  656.         ; Swap B/E, D/G
  657.     xchg    al,bh
  658.     mov    cx,di
  659.     xchg    cl,dh
  660.         ; Do 2x2 transpositions
  661.     mov    di,cx                ; need cl again
  662.     mov    cl,2
  663.     trans    di,ax,cl,3333h
  664.     trans    dx,bx,cl,3333h
  665.     mov    cx,di                ; done shifting >1
  666.         ; Do 1x1 transpositions
  667.     trans    bx,ax,1,5555h
  668.     trans    dx,cx,1,5555h
  669.         ; Store result
  670.     mov    si,sp
  671.     mov    di,ss:[si+20]            ; dist
  672.     lds    si,ss:[si+16]            ; outp
  673.     mov    [si],ah
  674. istore    macro    reg
  675.     add    si,di
  676.     mov    [si],reg
  677.     endm
  678.     istore    bh
  679.     istore    ch
  680.     istore    dh
  681.     istore    al
  682.     istore    bl
  683.     istore    cl
  684.     istore    dl
  685.         ; All done
  686.     pop    di
  687.     pop    si
  688.     pop    ds
  689.     ret
  690. _memflip8x8 ENDP
  691.  
  692.  
  693. utilasm_TEXT ENDS
  694.     END
  695.